import {PlotTypes} from '../enum/PlotTypes';
import {getStyle} from './DomUtil';
import {Point} from '../type';
import {calculateNewCoordinateOfRotate, calculateNewCoordinateOfTranslate} from './index';

const rgb2Rgba = (color: string, opacity: number): string => {
    const rgbaAttr: Array<string> = color.match(/[\d.]+/g) as Array<string>;
    if (rgbaAttr.length >= 3) {
        const r: string = rgbaAttr[0];
        const g: string = rgbaAttr[1];
        const b: string = rgbaAttr[2];
        return `rgba(${r}, ${g}, ${b}, ${opacity})`;
    } else {
        return 'rgba(255, 255, 255, 1)';
    }
};

const getColor = (color: string): string => {
    const rgbaAttr: Array<string> = color.match(/[\d.]+/g) as Array<string>;
    if (rgbaAttr.length >= 3) {
        const r: string = rgbaAttr[0];
        const g: string = rgbaAttr[1];
        const b: string = rgbaAttr[2];
        return `rgb(${r}, ${g}, ${b})`;
    }
    return `rgb(255, 255, 255)`;
};

const getOpacity = (color: string): number => {
    let alp: number = 1;
    let rgbaReg = /rgba\([\d ]+(?:,([\d. ]+)){3}\)/;
    if (rgbaReg.test(color)) {
        alp = Number(color.replace(rgbaReg, '$1'));
    }
    return alp;
};

const formatPlotStyle = (type: PlotTypes, params: any): any => {
    switch (type) {
        case PlotTypes.TEXT_AREA:
            return {
                fontFamily: 'Microsoft Yahei UI',
                fontSize: 18,
                borderColor: 'rgb(255, 34, 125)',
                borderWeight: 2,
                borderOpacity: 0.5,
                borderStyle: 'solid',
                backgroundColor: 'rgb(255, 0, 255)',
                backgroundOpacity: 0.7
            };
        case PlotTypes.POINT:
            return {
                anchor: params.getImage().getAnchor(),
                url: params.getImage().getSrc()
            };
        case PlotTypes.CIRCLE:
            return {
                strokeColor: getColor(params.getStroke().getColor()),
                strokeWeight: Number(params.getStroke().getWidth()),
                strokeOpacity: getOpacity(params.getStroke().getColor()),
                strokeStyle: 'solid',
                fillColor: getColor(params.getFill().getColor()),
                fillOpacity: getOpacity(params.getFill().getColor())
            };
        case PlotTypes.FREE_HAND_LINE:
        case PlotTypes.SEGMENT_LINE:
        case PlotTypes.POLYLINE:
            return {
                color: getColor(params.getStroke().getColor()),
                weight: Number(params.getStroke().getWidth()),
                opacity: getOpacity(params.getStroke().getColor()),
                style: 'solid'
            };
        case PlotTypes.RECTANGLE:
        case PlotTypes.POLYGON:
        case PlotTypes.RECT_FLAG:
        case PlotTypes.TRIANGLE_FLAG:
        case PlotTypes.DOUBLE_ARROW:
        case PlotTypes.FINE_ARROW:
        case PlotTypes.STRAIGHT_ARROW:
        case PlotTypes.SQUAD_COMBAT:
            return {
                strokeColor: getColor(params.getStroke().getColor()),
                strokeWeight: Number(params.getStroke().getWidth()),
                strokeOpacity: getOpacity(params.getStroke().getColor()),
                fillColor: getColor(params.getFill().getColor()),
                fillOpacity: getOpacity(params.getFill().getColor())
            };
    }
};

const formatPlotData = (type: PlotTypes, feature: any): any => {
    const style: any = formatPlotStyle(type, feature.getStyle());
    switch (type) {
        case PlotTypes.POINT:
            return {
                point: feature.getGeometry().getPoints()[0],
                style: {...style, size: feature.getProperties().size}
            };
        case PlotTypes.FREE_HAND_LINE:
        case PlotTypes.SEGMENT_LINE:
        case PlotTypes.POLYLINE:
            return {
                path: feature.getGeometry().getPoints(),
                style
            };
        case PlotTypes.CIRCLE:
            return {
                radius: feature.getGeometry().getRadius(),
                path: feature.getGeometry().getPoints(),
                style
            };
        case PlotTypes.RECTANGLE:
            return {
                path: feature.getGeometry().getPoints(),
                style
            };
        case PlotTypes.POLYGON:
            return {
                path: feature.getGeometry().getPoints(),
                style
            };
        case PlotTypes.TEXT_AREA:
            return {
                center: feature.getPosition(),
                style
            };
        case PlotTypes.RECT_FLAG:
        case PlotTypes.TRIANGLE_FLAG:
        case PlotTypes.DOUBLE_ARROW:
        case PlotTypes.FINE_ARROW:
        case PlotTypes.STRAIGHT_ARROW:
        case PlotTypes.SQUAD_COMBAT:
            return {
                path: feature.getGeometry().getPoints(),
                style
            };
    }
};

const createControlPoints = (extent: Array<number>): Array<Array<number>> => {
    const bottomLeftX: number = extent[0];
    const bottomLeftY: number = extent[1];
    const topRightX: number = extent[2];
    const topRightY: number = extent[3];
    const halfX: number = (bottomLeftX + topRightX) * 0.5;
    const halfY: number = (bottomLeftY + topRightY) * 0.5;

    return [
        [bottomLeftX, bottomLeftY],
        [halfX, bottomLeftY],
        [topRightX, bottomLeftY],
        [topRightX, halfY],
        [topRightX, topRightY],
        [halfX, topRightY],
        [bottomLeftX, topRightY],
        [bottomLeftX, halfY],
        [halfX, halfY]
    ];
};

const getBoundCenterPoint = (extent: number[]): Point => {
    const bottomLeftX: number = extent[0];
    const bottomLeftY: number = extent[1];
    const topRightX: number = extent[2];
    const topRightY: number = extent[3];
    const halfX: number = (bottomLeftX + topRightX) * 0.5;
    const halfY: number = (bottomLeftY + topRightY) * 0.5;
    return [halfX, halfY];
};

const getControlPixelsByCenter = (centerPixel: number[], dom: HTMLElement, type?: string): number[][] => {
    const halfW: number = parseInt(getStyle(dom, 'width')) * 0.5;
    const halfH: number = parseInt(getStyle(dom, 'height')) * 0.5;
    const [x, y] = centerPixel;
    return [
        [x - halfW, y - halfH],
        [x + halfW, y - halfH],
        [x + halfW, y + halfH],
        [x - halfW, y + halfH]
    ];
};

const getAnchorPoint = () => {

};

const updateControlPixels = (center: Point, distancePixel: Point, type: string): Array<Point> => {
    const [centerX, centerY] = center;
    const [disX, disY] = distancePixel;
    if (type === PlotTypes.CIRCLE) {
        const newDisValue: number = Math.max(disX, disY);
        return [
            [centerX - newDisValue, centerY - newDisValue],
            [centerX + newDisValue, centerY - newDisValue],
            [centerX + newDisValue, centerY + newDisValue],
            [centerX - newDisValue, centerY + newDisValue]
        ];
    }
    return [
        [centerX - disX, centerY - disY],
        [centerX + disX, centerY - disY],
        [centerX + disX, centerY + disY],
        [centerX - disX, centerY + disY]
    ];
};

const updateControlCoordinateByRadians = (points: Array<Point>, radians: number, centerCoordinate: Point): Array<Point> => {
    return calculateNewCoordinateOfRotate(points, centerCoordinate, radians);
};

const updateControlCoordinateByTranslate = (points: Array<Point>, translate: Point): Array<Point> => {
    return calculateNewCoordinateOfTranslate(points, translate);
};

const getBoundByPixels = (pixels: Array<Array<number>>): Array<number> => {
    const [x1, y1] = pixels[0];
    const [x2, y2] = pixels[pixels.length - 2];
    return [Math.floor(Math.abs(x2 - x1)), Math.floor(Math.abs(y2 - y1))];
};

export {
    rgb2Rgba,
    formatPlotData,
    createControlPoints,
    getBoundCenterPoint,
    getControlPixelsByCenter,
    getAnchorPoint,
    updateControlPixels,
    updateControlCoordinateByRadians,
    updateControlCoordinateByTranslate,
    getBoundByPixels
};
